package com.hxzy.tms.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.hxzy.tms.Assert;
import com.hxzy.tms.SessionHolder;
import com.hxzy.tms.dao.BaseDao.Params;
import com.hxzy.tms.dao.ProjectDao;
import com.hxzy.tms.dao.TeamDao;
import com.hxzy.tms.dao.TeamUserDao;
import com.hxzy.tms.dao.UserDao;
import com.hxzy.tms.entity.Project;
import com.hxzy.tms.entity.Team;
import com.hxzy.tms.entity.TeamUser;
import com.hxzy.tms.entity.User;
import com.hxzy.tms.service.ServiceResult;
import com.hxzy.tms.service.TeamService;

public class DefaultTeamService implements TeamService {
    private TeamDao teamDao;
    private UserDao userDao;
    private TeamUserDao teamUserDao;
    private ProjectDao projectDao;

    public ServiceResult<List<Team>> userCreateTeams(long userId, Integer status) {
        List<Params> params = new ArrayList<Params>();
        String sql = "from Team where userCreate.id = :user_id order by gmtCreate desc";
        params.add(new Params("user_id", userId));
        if (status != null) {
            sql += " and status = :status";
            params.add(new Params("status", status));
        }

        sql += " order by gmtCreate desc";

        List<Team> teamList = teamDao.read(sql, params);

        return new ServiceResult<List<Team>>(1, teamList);
    }

    public ServiceResult<List<TeamUser>> userJoinedTeams(long userId) {
        Assert.greaterThan(userId, 0L, "id 必须大于 0");
        String hql = "from TeamUser where user.id = :user_id order by gmtCreate desc";
        List<TeamUser> users = teamUserDao.read(hql, new Params("user_id", userId));
        for (TeamUser u : users) {
            u.getTeam().getName();
            u.getUser().getNickname();
        }
        return new ServiceResult<List<TeamUser>>(1, users);
    }

    public ServiceResult<Team> update(long id, String name, String desc, String intro, String subdomain, Date gmtBegin,
            Date gmtEnd, Integer status) {
        Assert.greaterThan(id, 0L, "id 必须大于 0");
        Assert.notBlank(name, "name 不能为空");
        Assert.notBlank(desc, "desc 不能为空");
        Assert.notBlank(subdomain, "subdomain 不能为空");
        Assert.notEmpty(gmtBegin, "开始时间不能为空");
        Assert.notEmpty(gmtEnd, "结束时间不能为空");
        Assert.notEmpty(SessionHolder.get(), "必须是登录用户才能创建团队");

        if (teamDao.read(Team.class, id) != null
                && !teamDao.read(Team.class, id).getUserCreate().getId().equals(SessionHolder.get().getId())) {
            return new ServiceResult<Team>(-5, null, "只能编辑自己的团队");
        }

        return saveOrUpdate(id, name, desc, intro, null, gmtBegin, gmtEnd, status);
    }

    public ServiceResult<Team> create(String name, String desc, String intro, String subdomain, Date gmtBegin,
            Date gmtEnd, Integer status) {
        Assert.notBlank(name, "name 不能为空");
        Assert.notBlank(desc, "desc 不能为空");
        Assert.notBlank(subdomain, "subdomain 不能为空");
        Assert.notEmpty(gmtBegin, "开始时间不能为空");
        Assert.notEmpty(gmtEnd, "结束时间不能为空");
        Assert.notEmpty(SessionHolder.get(), "必须是登录用户才能创建团队");

        if (!(subdomain.charAt(0) >= 'a' && subdomain.charAt(0) <= 'z')) {
            return new ServiceResult<Team>(-2, null, "团队二级域名首字母必须是小写字母 a-z");
        }

        String pattern = "^([a-zA-Z]{1}[a-zA-Z0-9]{3,20})$";
        if (!Pattern.matches(pattern, subdomain)) {
            return new ServiceResult<Team>(-6, null, "个性域名只能是数字和字母组合，首字符必须是字母");
        }

        return saveOrUpdate(null, name, desc, intro, subdomain, gmtBegin, gmtEnd, status);
    }

    private ServiceResult<Team> saveOrUpdate(Long id, String name, String desc, String intro, String subdomain,
            Date gmtBegin, Date gmtEnd, Integer status) {

        if (gmtEnd.getTime() <= gmtBegin.getTime()) {
            return new ServiceResult<Team>(-1, null, "开始时间必须早于预计结束时间");
        }

        List<Team> teams = new ArrayList<Team>();
        if (id != null) {
            teams = teamDao.read("from Team where name = :name and id != :id", new Params("name", name),
                    new Params("id", id));
        } else {
            teams = teamDao.read("from Team where name = :name", new Params("name", name));
        }
        if (!teams.isEmpty()) {
            return new ServiceResult<Team>(-3, null, "团队名字重复");
        }

        if (!StringUtils.isBlank(subdomain)) {
            if (id != null) {
                teams = teamDao.read("from Team where subdomain = :subdomain and id != :id",
                        new Params("subdomain", subdomain), new Params("id", id));
            } else {
                teams = teamDao.read("from Team where subdomain = :subdomain", new Params("subdomain", subdomain));
            }
            if (!teams.isEmpty()) {
                return new ServiceResult<Team>(-4, null, "团队个性域名重复");
            }
        }

        Team team = (id != null && (teamDao.read(Team.class, id) != null)) ? teamDao.read(Team.class, id) : new Team();
        team.setName(name);
        team.setDesc(desc);
        team.setIntro(intro);
        if (subdomain != null) {
            team.setSubdomain(subdomain);
        }
        team.setStatus(status == null ? 1 : status);

        if (id != null) {
            team.setUserModified(SessionHolder.get());
            team.setGmtModified(System.currentTimeMillis() / 1000);
        } else {
            team.setUserCreate(SessionHolder.get());
            team.setGmtCreate(System.currentTimeMillis() / 1000);
            team.setGmtModified(0L);
        }

        team.setGmtBegin(gmtBegin.getTime() / 1000);
        team.setGmtEnd(gmtEnd.getTime() / 1000);
        if (id == null) {
            team.setUserCount(0);
        }

        if (id != null) {
            team.setId(id);
            teamDao.merge(team);
        } else {
            teamDao.create(team);
        }
        return new ServiceResult<Team>(1, team);
    }

    public List<Team> list(Integer status) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("status", status);

        List<Team> teamList = teamDao.read("from Team where status = :status order by gmtCreate desc", param);
        return teamList;
    }

    public int invite(long uid, long teamId, String email) {
        // 1. 三个参数都不能为空，且是合法的
        if (uid <= 0) {
            throw new IllegalArgumentException("uid is less than or equal 0.");
        }
        if (StringUtils.isBlank(email)) {
            throw new IllegalArgumentException("email is null or empty.");
        }
        if (teamId <= 0) {
            throw new IllegalArgumentException("teamId is less than or equal 0.");
        }

        // 2. 数据逻辑的检查，uid 对应的用户是 team 的创建者 id
        Team team = null;
        team = teamDao.read(Team.class, teamId);
        if (!team.getUserCreate().getId().equals(uid)) {
            return -3; // throw new
                       // IllegalArgumentException(String.format("用户id
                       // %s 不是团队 %s 创建者 ", uid, teamId));
        }

        Map<String, Object> param = new HashMap<String, Object>();
        param.put("email", email);
        List<User> inviteUsers = userDao.read("from User where email = :email", param);
        if (inviteUsers.isEmpty()) {
            return -1; // email 对应的用户不存在
        }
        User inviteUser = inviteUsers.get(0);
        if (inviteUser.getId().equals(SessionHolder.get().getId())) {
            return -4;
        }

        // 3. 判断用户是否已经存在在当前组里
        Map<String, Object> param2 = new HashMap<String, Object>();
        param2.put("user_id", inviteUser.getId());
        param2.put("team_id", teamId);
        List<TeamUser> teamUsers = teamUserDao.read("from TeamUser where user.id = :user_id and team.id = :team_id ",
                param2);
        if (!teamUsers.isEmpty()) {
            return -2; // 用户已经加入了该团队
        }

        // 4. 写入 team_user 表
        TeamUser teamUser = new TeamUser();
        teamUser.setUser(inviteUser);
        teamUser.setTeam(team);
        teamUser.setUserNickname(inviteUser.getNickname());
        teamUser.setStatus(1);
        teamUser.setUidCreate(uid);
        teamUser.setUidModified(null);
        teamUser.setGmtCreate(System.currentTimeMillis() / 1000);
        teamUser.setGmtModified(0L);

        teamUserDao.create(teamUser);

        team = teamDao.read(Team.class, teamId);
        team.setUserCount(team.getUserCount() + 1);
        teamDao.update(team);

        return 1;
    }

    public ServiceResult<Team> read(long id) {
        Team team = teamDao.read(Team.class, id);
        return new ServiceResult<Team>(1, team);
    }

    public ServiceResult<Team> read(String domain) {
        List<Team> teams = teamDao.read("from Team where subdomain = :subdomain", new Params("subdomain", domain));
        return new ServiceResult<Team>(1, teams.isEmpty() ? null : teams.get(0));
    }

    public ServiceResult<List<User>> members(long teamId) {
        List<User> teamUsers = teamUserDao.teamUsers(teamId);
        return new ServiceResult<List<User>>(1, teamUsers, null);
    }

    public ServiceResult<Set<Project>> projects(long teamId) {
        Team team = teamDao.read(Team.class, teamId);
        return new ServiceResult<Set<Project>>(1, team.getProjects(), null);
    }

    public ServiceResult<Project> create(long teamId, String title, String desc) {
        Assert.notBlank(title, "标题不能为空");
        Assert.notBlank(desc, "描述不能为空");
        Assert.greaterThan(teamId, 0L, "团队 id 大于 0");
        Assert.notEmpty(SessionHolder.get(), "请登录");

        Team team = teamDao.read(Team.class, teamId);
        Assert.notEmpty(team, "团队不存在");

        if (!team.getUserCreate().getId().equals(SessionHolder.get().getId())) {
            return new ServiceResult<Project>(-2, null, "只有团队的创建人才能给本团队创建项目");
        }

        List<Project> projects = projectDao.read("from Project where title = :title and team.id = :team_id ",
                new Params("title", title), new Params("team_id", team.getId()));
        if (!projects.isEmpty()) {
            return new ServiceResult<Project>(-1, null, "重名");
        }

        Project project = new Project();

        project.setTitle(title);
        project.setDesc(desc);
        project.setGmtCreate(System.currentTimeMillis() / 1000);
        project.setGmtModified(0L);
        project.setUserCreate(SessionHolder.get());
        project.setTeam(team);
        project.setTaskCount(0);
        projectDao.create(project);

        return new ServiceResult<Project>(1, project);
    }

    public ServiceResult<Project> readProject(long projectId) {
        Project project = projectDao.read(projectId);
        if (project != null) {
            project.getTeam().getName();
        }
        return new ServiceResult<Project>(1, project);
    }

    public ServiceResult<Project> update(long projectId, long teamId, String title, String desc, int taskCount) {
        return null;
    }

    public TeamDao getTeamDao() {
        return teamDao;
    }

    public void setTeamDao(TeamDao teamDao) {
        this.teamDao = teamDao;
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public TeamUserDao getTeamUserDao() {
        return teamUserDao;
    }

    public void setTeamUserDao(TeamUserDao teamUserDao) {
        this.teamUserDao = teamUserDao;
    }

    public ProjectDao getProjectDao() {
        return projectDao;
    }

    public void setProjectDao(ProjectDao projectDao) {
        this.projectDao = projectDao;
    }

}
